package com.matt.service.impl;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Joiner;
import com.matt.commons.dto.sso.StaffDTO;

import com.matt.controller.po.ClienteleSortCountPO;
import com.matt.domain.*;
import com.matt.foundation.constant.ContractConstant;

import com.matt.foundation.dto.crm.ContractInfoDTO;
import com.matt.foundation.utils.DateUtil;
import com.matt.foundation.vo.*;
import com.matt.remoteCall.DTO.RoleDTO;
import com.matt.remoteCall.DTO.StaffPageDO;
import com.matt.repository.ClienteleRepository;
import com.matt.repository.ContractRepository;
import com.matt.repository.base.*;
import com.matt.service.ContractProductService;
import com.matt.service.CrmCountService;
import com.matt.remoteCall.SsoCallService;
import com.matt.service.TeachCallService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * *******************************
 * Created by Ron.
 * form com.matt
 * on 2018/09/29
 * *******************************
 */
@Service
public class CrmCountServiceImpl implements CrmCountService {

    @Autowired
    private ClienteleNativeRepository clienteleNativeRepository;
    @Autowired
    private ClienteleRepository clienteleRepository;
    @Autowired
    private ContractNativeRepository contractNativeRepository;
    @Autowired
    private SsoCallService ssoCallService;
    @Autowired
    private LeadsNativeRepository leadsNativeRepository;
    @Autowired
    private LeadsLinkClienteleNativeRepository leadsLinkClienteleNativeRepository;
    @Autowired
    private WeekPaperNativeRepository weekPaperNativeRepository;
    @Autowired
    private TeachCallService teachCallService;
    @Autowired
    private ContractRepository contractRepository;

    @Autowired
    private ContractProductService contractProductService;

    @Override
    public Long followClienteleNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return clienteleNativeRepository.followClienteleNum(staffId,begin,end);
    }

    @Override
    public Long signAllContractNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return contractNativeRepository.signAllContractNum(staffId,begin,end);
    }

    @Override
    public Long signFormalContractNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return contractNativeRepository.signFormalContractNum(staffId,begin,end);
    }

    @Override
    public Long signEffectiveContractNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return contractNativeRepository.signEffectiveContractNum(staffId,begin,end);
    }

    @Override
    public Long viewClienteleNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return clienteleNativeRepository.viewClienteleNum(staffId,begin,end);
    }

    @Override
    public Long increaseClienteleNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return clienteleNativeRepository.increaseClienteleNum(staffId,begin,end);
    }

    @Override
    public Long arriveLeadsNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return leadsNativeRepository.arriveLeadsNum(staffId,begin,end);
    }

    @Override
    public Long areaContractNum(String areaId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return contractNativeRepository.areaContractNum(areaId,begin,end);
    }

    @Override
    public Long proceedContractNum(String staffId, String date) {
        Date begin  = DateUtil.getBeginOfMonth(DateUtil.parseToDate(date));
        Date end = DateUtil.parseToDate(date);
        return contractNativeRepository.proceedContractNum(staffId,begin,end);
    }

    @Override
    public Integer pushFollowNum(String staffId) {
        return leadsLinkClienteleNativeRepository.pushFollowNum(staffId);
    }

    @Override
    public WeekPaperAdviserVo getAdviserWeekData(String areaId, String staffId, String date) {

        WeekPaperAdviserVo vo = weekPaperNativeRepository.getTeacherWeekData(areaId, staffId, date);

        StaffDTO staff = ssoCallService.getStaffDTO(null, staffId);
        vo.setHeadImgUrl(staff.getHeadImgUrl());
        vo.setStaffName(staff.getRealName());

        List<RoleDTO> roles = ssoCallService.getStaffRoleList(null, staff.getId());
        if (roles != null && roles.size() > 0){
            String rolesStr = roles.stream().map(o -> o.getRoleName()).collect(Collectors.joining(","));
            vo.setPositionName(rolesStr);
        }

        return vo;
    }

    @Override
    public WeekPaperAreaVo getAreaWeekData(String areaId,String date) {
        WeekPaperAreaVo vo = weekPaperNativeRepository.getAreaWeekData(areaId,date);
        //优秀顾问
        List<GoodAdviserVo> adviserVos = new ArrayList<GoodAdviserVo>();

        List<StaffPageDO> staffs = ssoCallService.getAreaStaffListByPermission(null, "crm::leads", null );

       for(StaffPageDO staff : staffs){
          int totalNum = weekPaperNativeRepository.getTotalNumByStaffId(staff.getId(),date);
           adviserVos.add(GoodAdviserVo.of(staff.getId(),staff.getRealName(),staff.getHeadImgUrl(),staff.getPositionName(),totalNum));
       }


        Collections.sort(adviserVos);
        vo.setExcellentAdviserName(adviserVos.size() > 0 ? adviserVos.get(0).getRealName() : "");
        vo.setExcellentAdviserId(adviserVos.size() > 0 ? adviserVos.get(0).getStaffId() : "");
        vo.setExcellentAdviserUrl(adviserVos.size() > 0 ? adviserVos.get(0).getHeadImgUrl() : "");
        vo.setExcellentAdviserPosition(adviserVos.size() > 0 ? adviserVos.get(0).getPositionName() : "");
        return vo;
    }

    @Override
    public Long adviserChildCheckInCount(String staffId, String date) {
        //查询顾问对应进行中的合同客户
        List<String> clientels = contractNativeRepository.findByStaffIdAndStatus(staffId, ContractConstant.Status.NORMAL.codeOf());
        //教务系统查询 客户对应的宝宝的签到数
        Long count = teachCallService.findCountByClienteleIds(Joiner.on(",").join(clientels), date);
        return count;
    }

    @Override
    public ContractVo findByClienteleIdDesc(String areaId, String clienteleId) {
        List<ContractVo> list = contractNativeRepository.findListByClienteleIdDesc(areaId,clienteleId);
        if (list.size()>0){
            return list.get(0);
        }
        return new ContractVo();
    }

    @Override
    public List<ChildrenContractInfoRecord> updateContract(StaffDTO staffDTO, String clienteleId, String date, List<WorkDate> workDateList, Integer day,Integer type) {
        List<Contract> list = contractNativeRepository.findByClienteleIdList(staffDTO.getAreaId(),clienteleId,date,date);
        List<ChildrenContractInfoRecord> contractInfoRecordList = new ArrayList<>();
        for (int i = 0; i <list.size() ; i++) {
            Contract contract = list.get(i);
            if (contract.getSurplusLeaveDay()>day){
                ChildrenContractInfoRecord childrenContractInfoRecord = new ChildrenContractInfoRecord();
                childrenContractInfoRecord.setClienteleId(contract.getClienteleId());
                childrenContractInfoRecord.setContractId(contract.getId());
                childrenContractInfoRecord.setCreatedBy(staffDTO.getId());
                childrenContractInfoRecord.setCreatedName(staffDTO.getRealName());
                childrenContractInfoRecord.setSurplusLeaveDay(contract.getSurplusLeaveDay());
                childrenContractInfoRecord.setSurplusOriginalLeaveDay(contract.getSurplusLeaveDay());
                childrenContractInfoRecord.setRemark(staffDTO.getRealName()+"手动接口添加合同"+day+"天");
                //查询合同信息，便于修改
                Contract contract1 = contractRepository.getOne(contract.getId());
                if (type == 1){
                    int f = 0 ;
                    //当请假天数大于可延长天数时，可延长天数变为剩余可延长天数
                    if (day > contract.getSurplusLeaveDay()) {
                        f = day;
                        day = contract.getSurplusLeaveDay();
                    }
                    //剩余请天数
                    childrenContractInfoRecord.setSurplusLeaveDay(contract.getSurplusLeaveDay() - day);
                    childrenContractInfoRecord.setRemark(staffDTO.getRealName()+"请假，合同延长"+day+"天");
                    if (f>0 && day ==0){
                        childrenContractInfoRecord.setRemark(staffDTO.getRealName()+"请假，合同可延长天数为0，合同未延长");
                    }
                    //赋值剩余请天数
                    contract1.setSurplusLeaveDay(contract.getSurplusLeaveDay() - day);
                }
                if (type == 2){
                    childrenContractInfoRecord.setRemark(staffDTO.getRealName()+"入户，合同减少"+day+"天");
                }
                Date endDate = getDateHoliday(workDateList,DateUtil.parseToDate(DateUtil.convertStr(contract.getEndDate())),day);
                System.out.println("结束时间：" +DateUtil.convertStr(contract.getEndDate()));
                System.out.println("结束时间修改后：" +DateUtil.convertStr(endDate));
                childrenContractInfoRecord.setEffectDay(day);
                childrenContractInfoRecord.setType(type);
                childrenContractInfoRecord.setNurseryEndDate(DateUtil.convertStr(endDate));
                childrenContractInfoRecord.setNurseryOriginalEndDate(DateUtil.convertStr(contract.getEndDate()));
                childrenContractInfoRecord.setSurplusOriginalLeaveDay(contract.getSurplusLeaveDay());
                contractInfoRecordList.add(childrenContractInfoRecord);

                //赋值结束合同日期
                contract1.setEndDate(endDate);

                contractRepository.save(contract1);
            }

        }
        return contractInfoRecordList;
    }

    public static Date getDateHoliday(List<WorkDate> workDateList, Date date,Integer day) {
        WorkDate workDate = null;
        for (int i = 0; i < workDateList.size(); i++) {
            if (StringUtils.equals(workDateList.get(i).getWorkDate(), DateUtil.convertStr(date))) {
                int count = i + day;
                if (day < 0){
                    //为负值的时候需要-1 ，因为循环+1了
                    count= count-1;
                }
                if (count <= workDateList.size() && count > 0) {
                    workDate = workDateList.get(count);
                    return DateUtil.parseToDate(workDate.getWorkDate());
                }
            }
        }
        try {
            return DateUtil.isWeekend(date,day);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public List<ContractVoV2> findByClienteleIdByList(String areaId , String clienteleId, String date) {
        if (Objects.nonNull(date) && !StringUtils.equals("null",date)){
            date =  date+" 00:00:00";
        }
        List<Contract>  contractList = contractNativeRepository.findByClienteleIdList(areaId,clienteleId,date,DateUtil.getMonthLast(date));
        List<ContractVoV2>  voList = new ArrayList<>();
        for (int i = 0; i < contractList.size(); i++) {
            ContractVoV2 vo  = new ContractVoV2();
            vo.setId(contractList.get(i).getId());
            vo.setBeginDate(DateUtil.convertStr(contractList.get(i).getBeginDate()));
            vo.setEndDate(DateUtil.convertStr(contractList.get(i).getEndDate()));
            vo.setSurplusLeaveDay(contractList.get(i).getSurplusLeaveDay());
            vo.setCode(contractList.get(i).getCode());
            vo.setName(contractList.get(i).getName());
            voList.add(vo);
        }
        return voList;
    }

    @Override
    public List<ContractInfoDTO> attendanceCount(String areaId, String clienteleId, String dateStr) {

        if (StringUtils.isBlank(dateStr)){
            return new ArrayList<>();
        }

        Date date = DateUtil.parseToDate(dateStr);
//        List<Contract>  areaContractList = contractNativeRepository.findByClienteleIdList(areaId,clienteleId,dateStr,DateUtil.getMonthLast(dateStr));
        List<Contract> areaContractList;
        if (StringUtils.isBlank(clienteleId)) {
            areaContractList = contractRepository.findValidContractsByAreaIdAndQueryDate(areaId, DateUtil.parseToDate(DateUtil.getMonthLast(dateStr)),date);
        }else{
            areaContractList = contractRepository.findValidContractsByAreaIdAndClienteleIdAndQueryDate(areaId, clienteleId, DateUtil.parseToDate(DateUtil.getMonthLast(dateStr)),date);
        }
        List<ContractInfoDTO> mapList  = new ArrayList<>();
        for (int q = 0; q < areaContractList.size(); q++) {

            Contract contract = areaContractList.get(q);

            ContractInfoDTO cInfo = new ContractInfoDTO();
            //客户id
            cInfo.setClienteleId(contract.getClienteleId());
            //客户已支付总金额
            cInfo.setPracticalAmount(contract.getPracticalAmount().doubleValue());
            //客户总金额
            cInfo.setTotalAmount(contract.getTotalAmount().doubleValue());
            //合同开始日期
            cInfo.setBeginDate(DateUtil.dateToymdhhmmss(contract.getBeginDate()));
            //合同结束日期
            cInfo.setEndDate(DateUtil.dateToymdhhmmss(contract.getEndDate()));
            //合同结束日期
            cInfo.setSurplusLeaveDay(contract.getSurplusLeaveDay());


            BigDecimal totalAmount = contract.getTotalAmount().setScale(2, RoundingMode.HALF_DOWN);

            //计算月数量
            double monthDouble = DateUtil.betweenMonthsV2(contract.getEndDate(), contract.getBeginDate());
            if (monthDouble > 0) {
                BigDecimal monthAmount = totalAmount.divide(new BigDecimal(monthDouble), 2, RoundingMode.HALF_DOWN);

                //月合同总金额
                cInfo.setMonthAmount(monthAmount.doubleValue());

                //查询一个可用的产品
                List <ContractProduct> products = contractProductService.findByContractId(contract.getId());

                double productMonthAmount = 0;
                for (ContractProduct cp : products){
                    if (cp.getProductType() == 1 /*托班*/){
                        productMonthAmount += cp.getPracticalAmount().doubleValue();
                    }
                }
                if (productMonthAmount > 0.0001){
                    cInfo.setMonthAmount(productMonthAmount);
                }
            }


            mapList.add(cInfo);
        }

        return mapList;
    }

    //BigDecimal 截取小数位，四舍五入
    public static BigDecimal convertNumber(BigDecimal bigDecimal, int divnum, int num){
        double a=bigDecimal.doubleValue();
        a=a/divnum;
        String numString="0.";
        for(int i=0;i<num;i++){
            numString+="0";
        }
        DecimalFormat df=new DecimalFormat(numString);
        return new BigDecimal(df.format(a).toString());
    }

    @Override
    public List<ClienteleSortCountPO> clienteleSortCount(String areaIds, String date) {
        List<Clientele>  list = clienteleRepository.findByAreaIdAndCreated( areaIds,  date);

        List<Object[]> channelCount = clienteleNativeRepository.findChannelCount(areaIds,  date);

        List<ClienteleSortCountPO> mapList = new ArrayList<>();
        for (int i = 0; i <channelCount.size(); i++) {
            String channelName = channelCount.get(i)[0].toString();
            String areaId = channelCount.get(i)[2].toString();
            ClienteleSortCountPO po = new ClienteleSortCountPO();
            po.setChannel(channelCount.get(i)[0].toString());
            int  count = Integer.valueOf(channelCount.get(i)[1].toString());
            po.setChannelCount(count);
            //跟随统计
            int follow = 0;
            //成交统计
            int deal = 0;
            for (int j = 0; j < list.size(); j++) {
                //当状态大于1时表示都跟进了
                if (StringUtils.equals(list.get(j).getChannel(), channelName)) {
                    if (list.get(j).getStatus() > 1){
                        follow++;
                    }
                    if (list.get(j).getStatus() == 6 || list.get(j).getStatus() == 11 ){
                        deal++;
                    }
                }
            }
            po.setFollowCount( follow);
            po.setFollowRate((int)((Double.valueOf(follow) / count)*100) + "%");
            po.setDealCount( deal);
            po.setAreaId(areaId);
            po.setDealRate((int)((Double.valueOf(deal) / count)*100) + "%");
            mapList.add(po);
        }
        return mapList;

    }

    @Override
    public List<Contract> findByClienteleIds(String clientelesIds) {
        clientelesIds = clientelesIds.substring(1,clientelesIds.length()-1);
        String ids[] = clientelesIds.split(",");
        clientelesIds = JSON.toJSON(ids).toString();
        clientelesIds = clientelesIds.substring(1,clientelesIds.length()-1).replaceAll(" ","");
        List<Contract> list = clienteleNativeRepository.findByClienteleIdIn(clientelesIds);
        return list;
    }
}
